package com.dstz.bpm.service;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import com.dstz.base.api.exception.BusinessException;
import com.dstz.base.api.exception.SerializeException;
import com.dstz.base.core.cache.ICache;
import com.dstz.bpm.api.constant.NodeType;
import com.dstz.bpm.api.engine.context.BpmContext;
import com.dstz.bpm.api.exception.BpmStatusCode;
import com.dstz.bpm.api.model.def.BpmProcessDef;
import com.dstz.bpm.api.model.def.IBpmDefinition;
import com.dstz.bpm.api.model.nodedef.BpmNodeDef;
import com.dstz.bpm.api.model.nodedef.impl.SubProcessNodeDef;
import com.dstz.bpm.api.service.BpmProcessDefService;
import com.dstz.bpm.core.manager.BpmDefinitionManager;
import com.dstz.bpm.core.model.BpmDefinition;
import com.dstz.bpm.engine.model.DefaultBpmProcessDef;
import com.dstz.bpm.engine.parser.BpmDefNodeHandler;
import com.dstz.bpm.engine.parser.BpmProcessDefParser;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Resource;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.RepositoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class DefaultBpmProcessDefService implements BpmProcessDefService {
   protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultBpmProcessDefService.class);
   @Resource
   ICache<DefaultBpmProcessDef> cf;
   @Resource
   private BpmDefinitionManager c;
   @Resource
   private BpmDefNodeHandler cg;
   @Resource
   RepositoryService repositoryService;

   public BpmProcessDef getBpmProcessDef(String processDefId) {
      return this.h(processDefId);
   }

   public List<BpmNodeDef> getNodeDefs(String processDefinitionId) {
      DefaultBpmProcessDef processDef = this.h(processDefinitionId);
      return processDef.getBpmnNodeDefs();
   }

   public BpmNodeDef getBpmNodeDef(String processDefinitionId, String nodeId) {
      List<BpmNodeDef> list = this.getNodeDefs(processDefinitionId);
      List<SubProcessNodeDef> listSub = new ArrayList();
      Iterator var5 = list.iterator();

      while(var5.hasNext()) {
         BpmNodeDef nodeDef = (BpmNodeDef)var5.next();
         if (nodeDef.getNodeId().equals(nodeId)) {
            return nodeDef;
         }

         if (nodeDef instanceof SubProcessNodeDef) {
            listSub.add((SubProcessNodeDef)nodeDef);
         }
      }

      if (listSub.size() > 0) {
         return this.b(listSub, nodeId);
      } else {
         return null;
      }
   }

   private BpmNodeDef b(List<SubProcessNodeDef> subList, String nodeId) {
      Iterator var3 = subList.iterator();

      ArrayList nestSub;
      do {
         if (!var3.hasNext()) {
            return null;
         }

         SubProcessNodeDef nodeDef = (SubProcessNodeDef)var3.next();
         List<BpmNodeDef> nodeList = nodeDef.getChildBpmProcessDef().getBpmnNodeDefs();
         nestSub = new ArrayList();
         Iterator var7 = nodeList.iterator();

         while(var7.hasNext()) {
            BpmNodeDef tmpDef = (BpmNodeDef)var7.next();
            if (tmpDef.getNodeId().equals(nodeId)) {
               return tmpDef;
            }

            if (tmpDef instanceof SubProcessNodeDef) {
               nestSub.add((SubProcessNodeDef)tmpDef);
            }
         }
      } while(nestSub.size() <= 0);

      return this.b(nestSub, nodeId);
   }

   public BpmNodeDef getStartEvent(String processDefId) {
      DefaultBpmProcessDef processDef = this.h(processDefId);
      List<BpmNodeDef> list = processDef.getBpmnNodeDefs();
      Iterator var4 = list.iterator();

      BpmNodeDef nodeDef;
      do {
         if (!var4.hasNext()) {
            return null;
         }

         nodeDef = (BpmNodeDef)var4.next();
      } while(!nodeDef.getType().equals(NodeType.START));

      return nodeDef;
   }

   public List<BpmNodeDef> getEndEvents(String processDefId) {
      List<BpmNodeDef> nodeList = new ArrayList();
      DefaultBpmProcessDef processDef = this.h(processDefId);
      List<BpmNodeDef> list = processDef.getBpmnNodeDefs();
      Iterator var5 = list.iterator();

      while(var5.hasNext()) {
         BpmNodeDef nodeDef = (BpmNodeDef)var5.next();
         if (nodeDef.getType().equals(NodeType.END)) {
            nodeList.add(nodeDef);
         }
      }

      return nodeList;
   }

   public void clean(String processDefId) {
      this.cf.delByKey("procdef_" + processDefId);
      BpmContext.cleanTread();
   }

   public List<BpmNodeDef> getStartNodes(String processDefId) {
      BpmNodeDef nodeDef = this.getStartEvent(processDefId);
      return nodeDef.getOutcomeNodes();
   }

   public boolean isStartNode(String defId, String nodeId) {
      List<BpmNodeDef> nodes = this.getStartNodes(defId);
      Iterator var4 = nodes.iterator();

      BpmNodeDef node;
      do {
         if (!var4.hasNext()) {
            return false;
         }

         node = (BpmNodeDef)var4.next();
      } while(!node.getNodeId().equals(nodeId));

      return true;
   }

   public boolean validNodeDefType(String defId, String nodeId, NodeType nodeDefType) {
      BpmNodeDef nodeDef = this.getBpmNodeDef(defId, nodeId);
      return nodeDef.getType().equals(nodeDefType);
   }

   public boolean isContainCallActivity(String defId) {
      DefaultBpmProcessDef processDef = this.h(defId);
      List<BpmNodeDef> list = processDef.getBpmnNodeDefs();
      Iterator var4 = list.iterator();

      BpmNodeDef nodeDef;
      do {
         if (!var4.hasNext()) {
            return false;
         }

         nodeDef = (BpmNodeDef)var4.next();
      } while(!nodeDef.getType().equals(NodeType.CALLACTIVITY));

      return true;
   }

   private DefaultBpmProcessDef h(String processDefinitionId) {
      DefaultBpmProcessDef processDef = (DefaultBpmProcessDef)BpmContext.getProcessDef(processDefinitionId);
      if (processDef != null) {
         return processDef;
      } else {
         processDef = this.a(processDefinitionId, true);
         if (processDef == null) {
            return null;
         } else {
            BpmContext.addProcessDef(processDefinitionId, processDef);
            return processDef;
         }
      }
   }

   private synchronized DefaultBpmProcessDef a(String processDefinitionId, Boolean isCache) {
      DefaultBpmProcessDef bpmProcessDef = null;
      if (isCache) {
         try {
            bpmProcessDef = (DefaultBpmProcessDef)this.cf.getByKey("procdef_" + processDefinitionId);
         } catch (SerializeException var5) {
            this.cf.delByKey("procdef_" + processDefinitionId);
            bpmProcessDef = null;
         }
      }

      if (bpmProcessDef != null) {
         return bpmProcessDef;
      } else {
         BpmDefinition bpmDef = (BpmDefinition)this.c.get(processDefinitionId);
         if (bpmDef == null) {
            throw new BusinessException(BpmStatusCode.DEF_LOST);
         } else {
            Assert.notEmpty(bpmDef.getActDefId(), "BpmDefinition actDefId cannot empty ！ 可能原因为：尚未完成流程设计，请检查流程定义 ", new Object[0]);
            bpmProcessDef = this.d(bpmDef);
            if (isCache) {
               this.cf.add("procdef_" + processDefinitionId, bpmProcessDef);
            }

            return bpmProcessDef;
         }
      }
   }

   public DefaultBpmProcessDef d(BpmDefinition bpmDef) {
      if (bpmDef == null) {
         return null;
      } else {
         JSONObject bpmDefSetting = JSONObject.parseObject(bpmDef.getDefSetting());
         if (bpmDefSetting == null) {
            throw new BusinessException("流程配置 bpmDefSetting 丢失！请检查流程定义 " + bpmDef.getKey());
         } else {
            DefaultBpmProcessDef bpmProcessDef = new DefaultBpmProcessDef();
            bpmProcessDef.setProcessDefinitionId(bpmDef.getId());
            bpmProcessDef.setName(bpmDef.getName());
            bpmProcessDef.setDefKey(bpmDef.getKey());
            BpmnModel bpmnModel = this.repositoryService.getBpmnModel(bpmDef.getActDefId());
            Process process = (Process)bpmnModel.getProcesses().get(0);
            this.cg.a(bpmProcessDef, process.getFlowElements());
            BpmProcessDefParser.a(bpmProcessDef, bpmDefSetting);
            bpmProcessDef.setJson(bpmDefSetting);
            return bpmProcessDef;
         }
      }
   }

   public List<BpmNodeDef> getNodesByType(String processDefinitionId, NodeType nodeType) {
      DefaultBpmProcessDef processDef = this.h(processDefinitionId);
      List<BpmNodeDef> list = processDef.getBpmnNodeDefs();
      List<BpmNodeDef> rtnList = new ArrayList();
      Iterator var6 = list.iterator();

      while(var6.hasNext()) {
         BpmNodeDef nodeDef = (BpmNodeDef)var6.next();
         if (nodeDef.getType().equals(nodeType)) {
            rtnList.add(nodeDef);
         }
      }

      return rtnList;
   }

   public List<BpmNodeDef> getAllNodeDef(String processDefinitionId) {
      List<BpmNodeDef> bpmNodeDefs = this.getNodeDefs(processDefinitionId);
      List<BpmNodeDef> rtnList = new ArrayList();
      this.a((List)bpmNodeDefs, (List)rtnList);
      return rtnList;
   }

   private void a(List<BpmNodeDef> bpmNodeDefs, List<BpmNodeDef> rtnList) {
      Iterator var3 = bpmNodeDefs.iterator();

      while(var3.hasNext()) {
         BpmNodeDef def = (BpmNodeDef)var3.next();
         rtnList.add(def);
         if (NodeType.SUBPROCESS.equals(def.getType())) {
            SubProcessNodeDef subProcessNodeDef = (SubProcessNodeDef)def;
            BpmProcessDef processDef = subProcessNodeDef.getChildBpmProcessDef();
            if (processDef != null) {
               List<BpmNodeDef> subBpmNodeDefs = processDef.getBpmnNodeDefs();
               this.a(subBpmNodeDefs, rtnList);
            }
         }
      }

   }

   public List<BpmNodeDef> getSignUserNode(String processDefinitionId) {
      List<BpmNodeDef> bpmNodeDefs = this.getAllNodeDef(processDefinitionId);
      List<BpmNodeDef> rtnList = new ArrayList();
      Iterator var4 = bpmNodeDefs.iterator();

      while(true) {
         BpmNodeDef bnd;
         do {
            if (!var4.hasNext()) {
               return rtnList;
            }

            bnd = (BpmNodeDef)var4.next();
         } while(!bnd.getType().equals(NodeType.START) && !bnd.getType().equals(NodeType.SIGNTASK) && !bnd.getType().equals(NodeType.USERTASK));

         rtnList.add(bnd);
      }
   }

   public IBpmDefinition getDefinitionById(String defId) {
      return (IBpmDefinition)this.c.get(defId);
   }

   public BpmProcessDef initBpmProcessDef(IBpmDefinition bpmDef) {
      try {
         DefaultBpmProcessDef def = this.d((BpmDefinition)bpmDef);
         BpmContext.cleanTread();
         this.cf.delByKey("procdef_" + bpmDef.getId());
         return def;
      } catch (Exception var3) {
         throw new BusinessException(var3.getMessage(), BpmStatusCode.PARSER_FLOW_ERROR, var3);
      }
   }

   public IBpmDefinition getDefinitionByActDefId(String actDefId) {
      return this.c.getDefinitionByActDefId(actDefId);
   }
}
